# 这是一个示例 Python 脚本。

# 按 Shift+F10 执行或将其替换为您的代码。
# 按 双击 Shift 在所有地方搜索类、文件、工具窗口、操作和设置。
from collections import defaultdict

from pythonosc import dispatcher
from pythonosc import osc_server
from pythonosc import osc_message_builder
from pythonosc import udp_client

import pygame

import datetime
import os

import time
import threading

from itertools import groupby
from playsound import playsound

global start_time_milliseconds
start_time_milliseconds = 0
log_path = ''
song_path = ''


def send_osc_message(ip='127.0.0.1', port=7000, address="", value=0):
    """
    发送一个OSC消息到指定地址和端口。

    参数:
    ip -- 目标IP地址，默认为本地环回地址'127.0.0.1'
    port -- 目标端口号，默认为3333
    address -- OSC地址，默认为'/test'
    value -- 发送的消息值，默认为1.0
    """
    client = udp_client.UDPClient(ip, port)
    msg = osc_message_builder.OscMessageBuilder(address=address)
    msg.add_arg(value)
    msg = msg.build()
    client.send(msg)

    client = udp_client.UDPClient(ip, port)
    msg = osc_message_builder.OscMessageBuilder(address=address)
    msg.add_arg(value)
    msg = msg.build()
    client.send(msg)




def print_handler(address, *args):
    """这是一个处理函数，每当接收到OSC消息时被调用。
    address: 消息的地址
    args: 消息的内容，可以有多个参数
    """
    current_time_milliseconds = int(time.time() * 1000)//100
    elapsed_time_milliseconds = current_time_milliseconds - start_time_milliseconds


    log = f"{elapsed_time_milliseconds}: {address}: {args}"


    print(f"Received OSC message: {address}: {args}")



    with open(log_path, "a") as log_file:
        log_file.write(log + "\n")


def osc_receive():
    # 创建一个调度器实例
    dispatcher_instance = dispatcher.Dispatcher()

    print("osc_receive")

    # 注册处理函数，这里我们为所有地址都注册同一个处理函数

    filter = [
        {"name": "Resolume Columns", "address": "/composition/columns/*/connect", "ignore_zero": True},
        {"name": "Resolume Clips", "address": "/composition/layers/*/clips/*/connect", "ignore_zero": True},
        {"name": "Resolume Decks", "address": "/composition/decks/*/select", "ignore_zero": True},
        {"name": "Resolume Master", "address": "/composition/master", "ignore_zero": False},
        {"name": "Resolume Master Speed", "address": "/composition/speed", "ignore_zero": False},
        {"name": "Resolume Layers opacity", "address": "/composition/layers/*/video/opacity", "ignore_zero": False},
        {"name": "Resolume Layers Transition Time", "address": "/composition/layers/*/transition/duration",
         "ignore_zero": False}
    ]

    for i in filter:
        address = i.get("address")
        dispatcher_instance.map(address, print_handler)


    # 启动OSC服务器，监听本机的7001端口
    server = osc_server.ThreadingOSCUDPServer(("127.0.0.1", 7001), dispatcher_instance)
    log = "Serving on {}".format(server.server_address)
    print(log)

    server.serve_forever()

def logc():
    # 获取当前日期和时间，格式化为字符串，用于文件名
    now = datetime.datetime.now()
    date_str = now.strftime("%Y-%m-%d_%H-%M-%S")  # 格式例如：2023-04-01_15-30-00

    # 构建日志文件名
    log_file_name = f"store\log_{date_str}.txt"
    log_file_path = os.path.join(os.getcwd(), log_file_name)  # 获取当前工作目录并拼接文件名

    # 打开文件并写入日志信息
    with open(log_file_path, "w") as log_file:
        log_file.write("")

    print(f"日志已保存至：{log_file_path}")

    return log_file_path

def osc_log_get():
    path = log_path
    with open(path, 'r') as file:
        data = file.read()

    print('data', data)

    return data

def time_get():
    global advance
    global delay
    current_time_milliseconds = int(time.time() * 1000) // 100
    elapsed_time_milliseconds = current_time_milliseconds - start_time_milliseconds

    try:
        elapsed_time_milliseconds = elapsed_time_milliseconds + advance - delay
    except:
        elapsed_time_milliseconds = elapsed_time_milliseconds

    return elapsed_time_milliseconds

def osc_log_send(data_dict):

    global advance
    global delay

    # 现在你可以通过索引值来查找对应的值列表

    current_time_milliseconds = int(time.time() * 1000)//100
    elapsed_time_milliseconds = current_time_milliseconds - start_time_milliseconds

    elapsed_time_milliseconds = elapsed_time_milliseconds+advance-delay

    print('current_time_milliseconds',elapsed_time_milliseconds)

    try:
        d_a = data_dict.get(elapsed_time_milliseconds)
        data_dict.pop(elapsed_time_milliseconds) #删除以免检查器重复调用
        print(d_a)
        for i in d_a:
            address = i[0]
            value = i[1]
            print(address,value)
            send_osc_message(address=address, value=value)
    except:
        pass


def play_song(song_path, volume=1.0):
    pygame.init()

    sound = pygame.mixer.Sound(song_path)
    channel = sound.play()

    while channel.get_busy():
        events = pygame.event.get()
        for event in events:
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_m:  # 静音/取消静音
                    channel.set_volume(0.0 if channel.get_volume() != 0 else 1.0)
                elif event.key == pygame.K_q:  # 停止播放
                    channel.stop()
                    break

        pygame.time.Clock().tick(10)
def timer_function(data_array):
    print("Timer triggered.")
    data_array = data_array
    osc_log_send(data_array)
    timer = threading.Timer(0.001, timer_function, args=([data_array]))
    timer.start()





def delay_set(*args):
    value = args[0]
    global delay
    delay = int(value)*10

def advance_set(*args):
    value = args[0]
    global advance
    advance = int(value)*10

def live(*args):
    log_pathc = args[0]
    livec(log_pathc)

def livec(log_pathc):
    global log_path
    log_path = log_pathc
    data = osc_log_get()
    data_array = data.split('\n')
    c_a = []
    for i in data_array:
        try:
            ci = i.split(": ")
            if ci[0].strip()=="song_path":
                global song_path
                song_path = ci[1].strip()
                thread = threading.Thread(target=fun_sound, args=[song_path])
                thread.start()
                # 记录脚本开始时的时间（毫秒）
                global start_time_milliseconds
                start_time_milliseconds = int(time.time() * 1000) // 100
                print(start_time_milliseconds)
            else:
                time1 = ci[0].strip()
                address = ci[1].strip()
                try:
                    arg = ci[2].strip()
                    arg1 = float(arg[1:-2])  # 去掉括号并转换为浮点数
                except:
                    arg1=0.0

                c_a.append((time1, address, arg1))
        except:
            pass

    # print(c_a)

    # 然后使用groupby按索引值分组

    c_b = {}

    for index, group in groupby(c_a, lambda x: x[0]):
        # group是一个迭代器，我们需要进一步迭代它来获取每个分组的元素
        group_list = list(group)
        print(f"Index {index}:")

        c_c = []
        for item in group_list:
            print(f"  - {item[1]}: {item[2]}")
            c_c.append((item[1], item[2]))

        c_b.update({int(index): c_c})

    print('c_b', c_b)

    timer = threading.Timer(0.001, timer_function, args=([c_b]))
    timer.start()

def fun_sound(*args):
    song_path = args[0]
    # print('song_path',song_path)
    # playsound(song_path)
    play_song(song_path)

def fun_sound_stop():
    global audio_thread
    audio_thread.join(0)  # 使用join()立即中断线程

def record(song_pathc):
    global start_time_milliseconds
    song_path = song_pathc

    global log_path
    log_path = logc()
    print('log_path', log_path)

    if song_path !="":
        with open(log_path, "a") as log_file:
            log = f"song_path: {song_path}"
            log_file.write(log + "\n")

        global audio_thread
        audio_thread = threading.Thread(target=fun_sound, args=[song_path])
        audio_thread.start()
        # 记录脚本开始时的时间（毫秒）
        start_time_milliseconds = int(time.time() * 1000) // 100
        print(start_time_milliseconds)
        osc_receive()
    else:
        # 记录脚本开始时的时间（毫秒）
        start_time_milliseconds = int(time.time() * 1000) // 100
        print(start_time_milliseconds)
        osc_receive()
















